package com.dc.base.view.recyclerview

import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ItemDecoration

class GridLayoutItemDecoration(context: Context, drawableResId: Int): ItemDecoration() {

    private val mDivider: Drawable?

    init {
        mDivider = ContextCompat.getDrawable(context, drawableResId)
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        var bottom = mDivider!!.intrinsicHeight
        var right = mDivider!!.intrinsicWidth
        // 留出分割线的位置，最右边和最下边不用留
        if (isLastColumn(view, parent)) {
            right = 0
        }
        if (isLastRow(view, parent)) {
            bottom = 0
        }
        outRect.bottom = bottom
        outRect.right = right
    }

    /**
     * 最后一列
     *
     * @param view   View
     * @param parent RecyclerView
     * @return boolean
     */
    private fun isLastColumn(view: View, parent: RecyclerView): Boolean {
        // 获取当前位置 --> 参考源码中getItemOffsets调用过时方法getItemOffsets中的itemPosition
        val currentPosition = (view.layoutParams as RecyclerView.LayoutParams).viewLayoutPosition
        // 获取列数
        val spanCount: Int = getSpanCount(parent)
        return (currentPosition + 1) % spanCount == 0
    }

    /**
     * 最后一行
     *
     * @param view   View
     * @param parent RecyclerView
     * @return boolean
     */
    private fun isLastRow(view: View, parent: RecyclerView): Boolean {
        val currentPosition = (view.layoutParams as RecyclerView.LayoutParams).viewLayoutPosition
        // 列数
        val spanCount: Int = getSpanCount(parent)

        // 行数 = 总的条目 / 列数 (不能整除则+1)
        val rowCount = if (parent.adapter!!.itemCount / spanCount == 0) parent.adapter!!
            .itemCount / spanCount else parent.adapter!!.itemCount / spanCount + 1

        // 返回 (当前位置 + 1) > (行数 - 1) * 列数
        return currentPosition + 1 > (rowCount - 1) * spanCount
    }

    /**
     * 获取RecyclerView列数
     *
     * @param recyclerView RecyclerView
     * @return int
     */
    private fun getSpanCount(recyclerView: RecyclerView): Int {
        // 获取列数
        val layoutManager = recyclerView.layoutManager
        if (layoutManager is GridLayoutManager) {
            return layoutManager.spanCount
        }
        return 1
    }

    override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        drawHorizontal(canvas, parent)
        drawVertical(canvas, parent)
    }

    /**
     * 绘制垂直方向
     *
     * @param canvas Canvas
     * @param parent RecyclerView
     */
    private fun drawVertical(canvas: Canvas, parent: RecyclerView) {
        val childCount = parent.childCount
        for (i in 0 until childCount) {
            val childView = parent.getChildAt(i)
            val params = childView.layoutParams as RecyclerView.LayoutParams
            val top = childView.top - params.topMargin
            val bottom = childView.bottom + params.bottomMargin
            val left = childView.right + params.rightMargin
            val right = left + mDivider!!.intrinsicWidth
            mDivider.setBounds(left, top, right, bottom)
            mDivider.draw(canvas)
        }
    }

    /**
     * 绘制水平方向
     *
     * @param canvas Canvas
     * @param parent RecyclerView
     */
    private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) {
        val childCount = parent.childCount
        for (i in 0 until childCount) {
            val childView = parent.getChildAt(i)
            val params = childView.layoutParams as RecyclerView.LayoutParams
            val left = childView.left - params.leftMargin
            val right = childView.right + mDivider!!.intrinsicWidth + params.rightMargin
            val top = childView.bottom + params.bottomMargin
            val bottom = top + mDivider.intrinsicHeight
            mDivider.setBounds(left, top, right, bottom)
            mDivider.draw(canvas)
        }
    }
}